import { Applet } from "@/api/interface/iot";
import { PropType } from "vue";
import {
	delAppResource,
	downloadAppResource,
	getAppServiceList,
	getResourceList,
	modAppResource,
	modAppService,
	saveAppResource,
	startAppService,
	stopAppService
} from "@/api/modules/applet/userApplet";
import DialogBox from "@/components/DialogBox";
import { exportExcel, showTips } from "@/utils/util";
import { ElMessageBox } from "element-plus";
import ProTable from "@/components/ProTable/index.vue";
import { ColumnProps } from "@/components/ProTable/interface";
import OnlineStatus from "@/components/Sansan/Status/OnlineStatus";
import LoggerDialog from "@/views/system/services/components/loggerDialog";
export default defineComponent({
	props: {
		detail: {
			type: Object as PropType<Applet.ResUserApplet>,
			default: () => {}
		}
	},
	setup(props) {
		onMounted(async () => {
			nextTick(() => {
				setTimeout(() => {
					//默认展开第一个节点
					const els: any = document.getElementsByClassName("el-table__expand-icon el-table__expand-icon--expanded");
					els[0].click();
				}, 100);
			});
		});
		const tableRef = ref();
		const uploadRef = ref();
		const maps = ref({});
		const tableData = ref<any>([{ id: props.detail.id, name: props.detail.id, hasChildren: true, folderPath: "", children: [] }]);
		const formRef = ref();
		const formRule = reactive({
			fileName: [{ required: true, message: "请输入文件夹名称", trigger: "change" }]
		});
		const fileDialog = ref<any>({
			visible: false,
			detail: { fileType: "folder" }
		});
		//懒加载表格数据
		const load = async (row, treeNode, resolve) => {
			let { code, result } = await getResourceList({
				appId: props.detail.id,
				folderPath: row.folderPath
					? row.folderPath.split(`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`)[1]
					: "",
				data: dataResource.value
			});
			if (code != 200 || result.length == 0) {
				tableRef.value.store.states.lazyTreeNodeMap.value[row.id] = [];
				resolve([]);
			} else {
				resolve(
					//组装数据
					result.map(item => {
						return {
							id: item.path,
							name: item.name,
							folderPath: item.path,
							hasChildren: item.isDir,
							modified: item.modified,
							isInvalidLink: item.isInvalidLink,
							isSymlink: item.isSymlink
						};
					})
				);
			}
			//缓存懒加载数据
			maps.value[row.id] = { row, treeNode, resolve };
		};
		//保存新增文件
		const validData = () => {
			formRef.value?.validate(async valid => {
				if (valid) {
					//新增文件夹，拼接文件夹路径
					if (fileDialog.value.detail.fileType == "folder") {
						let path = fileDialog.value.detail.folderPath
							? fileDialog.value.detail.folderPath.split(
									`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`
							  )[1] + `/${fileDialog.value.detail.fileName}`
							: `${fileDialog.value.detail.fileName}`;
						let { code, message } = await saveAppResource({
							appId: props.detail.id,
							fileType: fileDialog.value.detail.fileType,
							folderPath: path,
							data: dataResource.value
						});
						let ok = showTips(code, message);
						if (ok) {
							fileDialog.value.visible = false;
							refreshTree();
						}
					} else {
						uploadRef.value.submit();
					}
				}
			});
		};
		const removeFile = path => {
			ElMessageBox.confirm(`是否删除${path}文件？`, "提示", {
				confirmButtonText: "确定",
				cancelButtonText: "取消",
				type: "warning",
				draggable: true
			})
				.then(async () => {
					let { code, message } = await delAppResource({
						appId: props.detail.id,
						folderPath: path.includes("/") ? path.replace(/\/[^\/]*$/, "") : "",
						filename: path.includes("/") ? path.substring(path.lastIndexOf("/") + 1) : path,
						data: dataResource.value
					});
					let ok = showTips(code, message);
					if (ok) {
						refreshTree();
					}
				})
				.catch(() => {});
		};
		//编辑文件
		const modifyResource = row => {
			ElMessageBox.prompt("请输入需要修改的名称", "提示", {
				confirmButtonText: "确定",
				cancelButtonText: "取消",
				inputValue: row.name
			}).then(async ({ value }) => {
				let path = row.folderPath.split(`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`)[1];
				path = path.split(row.name)[0];
				let { code, message } = await modAppResource({
					appId: props.detail.id,
					folderPath: path,
					newName: value,
					filename: row.name,
					data: dataResource.value
				});
				let ok = showTips(code, message);
				if (ok) {
					refreshTree();
				}
			});
		};
		//上传文件
		const uploadExcel = async (param: any) => {
			let path = fileDialog.value.detail.folderPath
				? fileDialog.value.detail.folderPath.split(`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`)[1]
				: ``;
			let { code, message } = await saveAppResource({
				appId: props.detail.id,
				fileType: fileDialog.value.detail.fileType,
				folderPath: path,
				file: param.file,
				data: dataResource.value,
				svcName: fileDialog.value.detail.svcName,
				svcArg: fileDialog.value.detail.svcArg
			});
			let ok = showTips(code, message);
			if (ok) {
				fileDialog.value.visible = false;
				refreshTree();
			}
		};
		const refreshTree = () => {
			//刷新所有懒加载的缓存
			Object.keys(maps.value).map((key: any) => {
				let { row, treeNode, resolve } = maps.value[key];
				load(row, treeNode, resolve);
			});
			proTable.value.getTableList();
		};
		const proTable = ref<any>();
		const initParam = reactive<any>({ pageIndex: 1, pageSize: 20, appId: props.detail.id });
		// 表格配置项
		const columns: ColumnProps[] = [
			{ prop: "status", label: "状态" },
			{ prop: "name", label: "名称" },
			{ prop: "bin", label: "文件名" },
			{ prop: "arg", label: "启动参数" },
			{ prop: "path", label: "运行目录", width: 180 },
			{ prop: "retry", label: "重启次数" },
			{ prop: "createTime", label: "创建时间", width: 180 },
			{ prop: "updateTime", label: "更新时间", width: 180 },
			{ prop: "startTime", label: "启动时间", width: 180 },
			{ prop: "md5", label: "md5" },
			{ prop: "type", label: "安装方式" },
			{ prop: "operation", label: "操作", fixed: "right", width: 200 }
		];
		const dataCallback = (data: any) => {
			return {
				datalist: data.records,
				total: data.total || 0,
				pageIndex: data.current,
				pageSize: data.size
			};
		};

		const getTableList = async (params: any) => {
			return getAppServiceList(params);
		};
		const serviceDialog = ref<any>({
			visible: false,
			detail: {}
		});
		const stop = async row => {
			let { code, message } = await stopAppService({ id: row.id });
			showTips(code, "停止", message) && proTable.value.getTableList();
		};
		const start = async row => {
			let { code, message } = await startAppService({ id: row.id });
			showTips(code, "启动", message) && proTable.value.getTableList();
		};
		const validService = async () => {
			let { code, message } = await modAppService(serviceDialog.value.detail);
			showTips(code, "修改", message) && proTable.value.getTableList();
			loggerDialog.visible = false;
		};
		const loggerDialog = reactive<any>({
			detail: {},
			title: "服务日志",
			visible: false
		});
		const dataResource = ref(false);
		return () => {
			return (
				<div class="">
					<DialogBox
						width="400px"
						v-model:visible={fileDialog.value.visible}
						title={`${fileDialog.value.detail.folderPath}添加`}
						onConfirm={() => validData()}
					>
						<el-form model={fileDialog.value.detail} ref={formRef} rules={formRule} label-width="100px">
							<el-form-item label="文件类型" prop="fileType">
								<el-select v-model={fileDialog.value.detail.fileType}>
									<el-option label="文件夹" value="folder"></el-option>
									<el-option label="普通文件" value="general"></el-option>
									<el-option label="可执行文件" value="bin"></el-option>
									<el-option label="压缩包" value="zip"></el-option>
								</el-select>
							</el-form-item>
							{/* {fileDialog.value.detail.fileType == "zip" || fileDialog.value.detail.fileType == "bin" ? (
								""
							) : (
								<el-form-item
									prop="data"
									v-slots={{
										label: () => {
											return (
												<>
													<el-tooltip content="在当前目录创建软链，链接到数据目录中对应目录/文件，保证升级时不会丢失">
														<span class="iconfont iconinfo font-thin mr-1" />
													</el-tooltip>
													<span>数据目录</span>
												</>
											);
										}
									}}
								>
									<el-switch v-model={fileDialog.value.detail.data} />
								</el-form-item>
							)} */}

							{fileDialog.value.detail.fileType == "bin" ? (
								<>
									<el-form-item label="服务名称" prop="svcName">
										<el-input v-model={fileDialog.value.detail.svcName} placeholder="请输入服务名称" />
									</el-form-item>
									<el-form-item label="启动参数" prop="svcArg">
										<el-input v-model={fileDialog.value.detail.svcArg} placeholder="请输入启动参数" />
									</el-form-item>
								</>
							) : (
								""
							)}
							{fileDialog.value.detail.fileType == "folder" ? (
								<el-form-item label="文件夹名称" prop="fileName">
									<el-input v-model={fileDialog.value.detail.fileName} placeholder="请输入文件夹名称" />
								</el-form-item>
							) : (
								<el-form-item label="上传文件" prop="file">
									<el-upload class="w-full" ref={uploadRef} auto-upload={false} http-request={uploadExcel} limit={1}>
										<el-button>请选择文件</el-button>
									</el-upload>
								</el-form-item>
							)}
						</el-form>
					</DialogBox>
					<el-table
						height="400"
						ref={tableRef}
						data={tableData.value}
						row-key="id"
						lazy
						load={load}
						tree-props={{ children: "children", hasChildren: "hasChildren" }}
						default-expand-all
					>
						<el-table-column prop="name">
							{{
								header: () => {
									return (
										<div class="flex">
											<div>{dataResource.value ? "数据目录" : "应用目录"}</div>
											<el-link
												class="ml-6"
												type="primary"
												onClick={() => {
													dataResource.value = !dataResource.value;
													// tableData.value = [
													// 	{ id: props.detail.id, name: props.detail.id, hasChildren: true, folderPath: "", children: [] }
													// ];
													// maps.value = [];
													console.log(maps.value);
													refreshTree();
												}}
											>
												<span class={`iconfont iconrefresh-cw font-thin mr-1`} />
												目录切换
											</el-link>
										</div>
									);
								},
								default: (scope: any) => {
									return (
										<span
											class={`${scope.row.hasChildren ? "" : "cursor-pointer"}`}
											onClick={async () => {
												if (scope.row.hasChildren) return;
												let path = scope.row.folderPath.split(
													`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`
												)[1];
												path = path.split(scope.row.name)[0];
												const res = await downloadAppResource({
													appId: props.detail.id,
													folderPath: path,
													filename: scope.row.name,
													data: dataResource.value
												});
												exportExcel(res.data, scope.row.name);
											}}
										>
											{scope.row.isInvalidLink ? <span class={`iconfont text-red-500 iconalert-octagon font-thin`}></span> : ""}
											<span
												class={`iconfont ${
													scope.row.hasChildren
														? scope.row.isSymlink
															? "icongrid1"
															: "iconbx-folder"
														: scope.row.isSymlink
														? "iconserver1"
														: "iconbx-file"
												} font-thin mr-1`}
											/>
											{scope.row.name}
										</span>
									);
								}
							}}
						</el-table-column>
						<el-table-column prop="modified" label="修改日期" width="200px" align="center" />
						<el-table-column prop="operation" label="操作" width="200px" align="center">
							{{
								default: (scope: any) => {
									return (
										<div class="grid grid-cols-3 gap-1">
											{scope.row.hasChildren ? (
												<el-link
													type="primary"
													onClick={() => {
														fileDialog.value.visible = true;
														fileDialog.value.detail.folderPath = scope.row.folderPath;
														// fileDialog.value.detail.id = scope.row.id;
														// fileDialog.value.detail.name = scope.row.name;
													}}
												>
													<span class={`iconfont iconplus1 font-thin mr-1`} />
													添加
												</el-link>
											) : (
												<div></div>
											)}

											{scope.row.folderPath ? (
												<>
													<el-link
														type="primary"
														onClick={() => {
															modifyResource(scope.row);
														}}
													>
														<span class={`iconfont iconedit font-thin mr-1`} />
														编辑
													</el-link>
													<el-link
														type="danger"
														onClick={() => {
															removeFile(
																scope.row.folderPath.split(
																	`${dataResource.value ? "data/config/" : "app/"}${props.detail.id}/`
																)[1]
															);
														}}
													>
														<span class={`iconfont icontrash-2 font-thin mr-1`} />
														删除
													</el-link>
												</>
											) : null}
										</div>
									);
								}
							}}
						</el-table-column>
					</el-table>
					<DialogBox
						width="400px"
						v-model:visible={serviceDialog.value.visible}
						title="服务编辑"
						onConfirm={() => validService()}
					>
						<el-form model={serviceDialog.value.detail} label-width="100px">
							<el-form-item label="服务名称" prop="name">
								<el-input v-model={serviceDialog.value.detail.name} placeholder="请输入服务名称" />
							</el-form-item>
							<el-form-item label="启动参数" prop="arg">
								<el-input v-model={serviceDialog.value.detail.arg} placeholder="请输入启动参数" />
							</el-form-item>
						</el-form>
					</DialogBox>
					<LoggerDialog
						width="1024px"
						title={loggerDialog.title}
						v-model:visible={loggerDialog.visible}
						detail={loggerDialog.detail}
						footerLabel={["关闭"]}
					/>
					<ProTable
						height={"calc(100vh - 350px)"}
						ref={proTable}
						title="服务列表"
						columns={columns}
						requestApi={getTableList}
						initParam={initParam}
						searchCol={4}
						dataCallback={dataCallback}
					>
						{{
							status: (scope: any) => {
								let val = scope.row.status == "running";
								return <OnlineStatus v-model={val} onlineLabel="运行中" offlineLabel="已停止" />;
							},
							operation: (scope: any) => {
								return (
									<div class="grid grid-cols-3 gap-0">
										{scope.row.status == "running" ? (
											<el-link
												type="primary"
												onClick={() => {
													stop(scope.row);
												}}
											>
												<span class={`iconfont iconstop-circle1 font-thin mr-1`} />
												停止
											</el-link>
										) : (
											<el-link
												type="primary"
												onClick={() => {
													start(scope.row);
												}}
											>
												<span class={`iconfont iconplay-circle1 font-thin mr-1`} />
												启动
											</el-link>
										)}
										<el-link
											type="primary"
											onClick={() => {
												serviceDialog.value.visible = true;
												serviceDialog.value.detail.id = scope.row.id;
												serviceDialog.value.detail.name = scope.row.name;
												serviceDialog.value.detail.arg = scope.row.arg;
											}}
										>
											<span class={`iconfont iconedit font-thin mr-1`} />
											修改
										</el-link>
										<el-link
											type="primary"
											onClick={() => {
												loggerDialog.title = `【${scope.row.name}】运行日志`;
												loggerDialog.detail = scope.row;
												loggerDialog.visible = true;
											}}
										>
											<span class={`iconfont iconbx-file font-thin mr-1`} />
											日志
										</el-link>
									</div>
								);
							}
						}}
					</ProTable>
				</div>
			);
		};
	}
});
